package per.qiao.simplechian.core;

import per.qiao.simplechian.bo.NodeParam;
import per.qiao.simplechian.bo.NodeResult;

import java.io.Serializable;
import java.util.Objects;

/**
 * @author: qiaoyp
 * @Date: 2023/8/29 17:02
 * @Description:
 */
public abstract class DefaultNode implements PipelineActuator, Comparable<DefaultNode>, Serializable {

    private DefaultNode pre;

    private DefaultNode next;

    private int orderNum;

    public DefaultNode pre() {
        return this.pre;
    }

    public DefaultNode pre(DefaultNode node) {
        this.pre = node;
        return this;
    }


    public DefaultNode next(DefaultNode node) {
        this.next = node;
        return this;
    }

    public DefaultNode next() {
        return this.next;
    }

    @Override
    public NodeResult exec(NodeParam param, NodeResult preRtn) {
        if (preRtn == null || !preRtn.isContinueExec()) {
            return preRtn;
        }
        DefaultNode currentNode = this;
        NodeResult result = preRtn;
        while (currentNode != null) {
            // 执行当前节点
            result = currentNode.doExec(param, result);
            if (result == null || !result.isContinueExec()) {
                return result;
            }
            if (currentNode.next() == null) {
                return result;
            }
            currentNode = currentNode.next();
        }
        return result;
    }

    /**
     *
     * @param param     全链路参数
     * @param preRtn    上一个节点的执行结果
     * @return  当前节点返回的结果
     */
    protected abstract NodeResult doExec(NodeParam param, NodeResult preRtn);


    @Override
    public int compareTo(DefaultNode other) {
        return Integer.compare(this.getOrderNum(), other.getOrderNum());
    }

    @Override
    public int hashCode() {
        int result = this.getClass().getName().hashCode() * 31;
        result = 31 * result + (pre() != null ? pre().hashCode() : 0);
        result = 31 * result + (next() != null ? next().hashCode() : 0);
        result = 31 * result + this.getOrderNum();
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || this.getClass() != obj.getClass()) {
            return false;
        }
        DefaultNode other = (DefaultNode) obj;
        if (this.getOrderNum() != other.getOrderNum()) {
            return false;
        }
        return Objects.equals(this.pre(), other.pre()) && Objects.equals(this.next(), other.next());
    }

    public int getOrderNum() {
        return orderNum;
    }
}
